import re
from datetime import datetime, timedelta

from rest_framework.validators import UniqueValidator
from rest_framework import serializers

from apps.users.models import User, VerifyCode
from utils.constants import REGEX_MOBILE


class SmsSerializer(serializers.Serializer):
    # 发送短信序列化
    mobile = serializers.CharField(max_length=11)

    def validate_mobile(self, mobile):  # validate_字段  验证
        """
        验证手机号码
        :param data:
        :return:
        """
        print("--------------验证手机号ser----------------")
        # 手机是否注册
        if User.objects.filter(mobile=mobile).count():
            raise serializers.ValidationError("用户已经存在")

        # 验证手机号码是否合法
        if not re.match(REGEX_MOBILE, mobile):
            raise serializers.ValidationError("手机号码格式不正确")

        # 验证码发送频率，60秒发一次
        one_mintes_ago = datetime.now() - timedelta(hours=0, minutes=1, seconds=0)
        if VerifyCode.objects.filter(add_time__gt=one_mintes_ago, mobile=mobile).count():
            raise serializers.ValidationError("距离上一次发送未超过60s")

        return mobile


class UserRegSerializer(serializers.ModelSerializer):
    """
    用户
    """

    # 定义code字段
    code = serializers.CharField(
        max_length=4, min_length=4, required=True, write_only=True,
        error_messages={
            "blank": "请输入验证码",
            "required": "请输入验证码",
            "max_length": "验证码格式错误",
            "min_length": "验证码格式错误"
        },
        help_text="验证码"
    )

    # 验证用户名是否正确
    username = serializers.CharField(
        label="用户名", help_text="用户名", required=True, allow_blank=False,
        validators=[UniqueValidator(queryset=User.objects.all(), message="用户已经存在")]
    )

    # 密码，样式为密码,设置密码只能写
    password = serializers.CharField(
        style={'input_type': "password"},
        label=True,
        write_only=True,
        help_text="密码"
    )

    # 密码加密保存
    def create(self, validated_data):
        print("------------保存密码ser------------")
        user = super(UserRegSerializer, self).create(validated_data=validated_data)
        user.set_password(validated_data["password"])
        user.save()
        return user

    # 验证code
    def validate_code(self, code):
        print("-------------验证手机验证码ser-------------")
        # 用户未注册，以post方式提交信息，post的数据都保存在initial_data里面
        # username就是用户注册的手机号，验证码按添加时间倒序排序，为了后面验证过期，错误等
        verify_records = VerifyCode.objects.filter(mobile=self.initial_data['username']).order_by("-add_time")
        if verify_records:
            # 取最近的一个验证码
            last_record = verify_records[0]
            five_mintes_ago = datetime.now() - timedelta(hours=0, minutes=5, seconds=0)

            if five_mintes_ago > last_record.add_time:
                raise serializers.ValidationError("验证码过期")

            if last_record.code != code:
                raise serializers.ValidationError("验证码错误")

        else:
            raise serializers.ValidationError("验证码错误")

    def validate(self, attrs):
        # 前端没有传mobile值到后端，这里添加进来
        attrs['mobile'] = attrs['username']
        # code 是自己添加的，数据库中没有这个字段，验证完就删掉
        del attrs['code']
        return attrs

    class Meta:
        model = User
        fields = ("username", "code", "mobile", "password")


# serializers.py
from rest_framework.serializers import ModelSerializer, CharField, ValidationError, SerializerMethodField
from . import models
import re
from rest_framework_jwt.serializers import jwt_payload_handler, jwt_encode_handler

from django.utils import timezone
from rest_framework import serializers

from apps.users.models import User


class LoginAuthSerializer(serializers.ModelSerializer):
    """管理员序列化器类"""
    username = serializers.CharField(
        label='用户名')  # 如果不进行定义，那么会导致在进行序列化器 校验时按照User模型类中的username的约束进行，而此时又是post提交方式，所以如果没有此行，会出现 {"username":["A user with that username already exists."]}
    token = serializers.CharField(label='JWT Token', read_only=True)  # User模型类是没有token属性的，所以需要额外添加

    class Meta:
        model = User
        fields = ('id', 'username', 'password', 'token')

        extra_kwargs = {
            'password': {
                'write_only': True  # 这里设置密码只能够进行反序列化而不能序列化。否则的话会将密码放到json中返回 用户会看到，这样不安全
            }
        }

    def validate(self, attrs):
        # 获取username和password
        username = attrs['username']
        password = attrs['password']
        print("用户名和密码==", username, password)
        # 进行用户名和密码校验
        try:
            user = User.objects.get(username=username)  # is_staff 1表示管理员，可以修改数据库得到
            print("该用户存在----------")
        except User.DoesNotExist:
            print("用户名或密码错误----------")
            raise serializers.ValidationError('该用户名不存在')
        else:
            # 校验密码
            if not user.check_password(password):
                print("密码错误----------")
                raise serializers.ValidationError('密码错误')

            # 给attrs中添加user属性，保存登录用户
            attrs['user'] = user

        return attrs

    def create(self, validated_data):
        # 获取登录用户user
        user = validated_data['user']

        # 设置最新登录时间
        user.last_login = timezone.now()
        user.save()

        # 服务器生成jwt token, 保存当前用户的身份信息
        from rest_framework_jwt.settings import api_settings

        # 组织payload数据的方法
        jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
        # 生成jwt token数据的方法
        jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

        # 组织payload数据
        payload = jwt_payload_handler(user)
        # 生成jwt token
        token = jwt_encode_handler(payload)

        # 给user对象增加属性，保存jwt token的数据
        user.token = token

        return user
